/*
 * @Author: Jiarun
 * @Date: 2021-06-05 18:41:16
 * @LastEditors: Jiarun
 * @LastEditTime: 2021-06-08 08:06:40
 * @Description: 
 *****************************************
 * ADC 通道对应的引脚
 * ADC12_IN0 ~ ADC12_IN7		PA0 ~ PA7
 * ADC12_IN8 ~ ADC12_IN9		PB0 ~ PB1
 * ADC12_IN10 ~ ADC12_IN15		PC0 ~ PC5
 * ADC1_IN16(温度传感器)
 * ADC1_IN17(VREFINT)
 *****************************************
 */
#include "es_adc.h"
#include "es_gpio.h"


ADC_TypeDef * using_adc = 0;

/**
 * @description: 初始化ADCx
 * @param {ADC_TypeDef} *ADCx	选择 ADC 外设 ADC1 或 ADC2
 * @param {uint8_t} ADC_Channel	ADC 通道
 * @return None
 * @Sample adc_init(ADC1, 0);
 */
void adc_init(ADC_TypeDef * ADCx, uint8_t ADC_Channel)
{
	ADC_InitTypeDef ADC_InitStructure;
	
	using_adc = ADCx;
	if(ADC_Channel < 8)
		gpio_init(GPIOA, GPIO_Pin_0 << ADC_Channel, GPIO_Mode_AIN);
	else if(ADC_Channel < 10)
		gpio_init(GPIOB, GPIO_Pin_0 << (ADC_Channel - 8), GPIO_Mode_AIN);
	else if(ADC_Channel < 16)
		gpio_init(GPIOC, GPIO_Pin_0 << (ADC_Channel - 10), GPIO_Mode_AIN);
	
		
	if(ADC1 == ADCx)
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC1, ENABLE);
	else if(ADC2 == ADCx)
		RCC_APB2PeriphClockCmd(RCC_APB2Periph_ADC2, ENABLE);
	
	RCC_ADCCLKConfig(RCC_PCLK2_Div6);
	ADC_DeInit(ADCx);
	ADC_InitStructure.ADC_Mode = ADC_Mode_Independent;	//ADC工作模式:ADC1和ADC2工作在独立模式
	ADC_InitStructure.ADC_ScanConvMode = DISABLE;	//模数转换工作在单通道模式
	ADC_InitStructure.ADC_ContinuousConvMode = DISABLE;	//模数转换工作在单次转换模式
	ADC_InitStructure.ADC_ExternalTrigConv = ADC_ExternalTrigConv_None;	//转换由软件而不是外部触发启动
	ADC_InitStructure.ADC_DataAlign = ADC_DataAlign_Right;	//ADC数据右对齐
	ADC_InitStructure.ADC_NbrOfChannel = 1;	//顺序进行规则转换的ADC通道的数目
	ADC_Init(ADCx, &ADC_InitStructure);	//根据ADC_InitStruct中指定的参数初始化外设ADCx的寄存器   
	
	if(16 == ADC_Channel)
		ADC_TempSensorVrefintCmd(ENABLE);
	
	ADC_Cmd(ADCx, ENABLE);	//使能指定的ADC
	
	ADC_ResetCalibration(ADCx);	//使能复位校准  
	while(ADC_GetResetCalibrationStatus(ADCx));	//等待复位校准结束
	
	ADC_StartCalibration(ADCx);	 //开启AD校准
	while(ADC_GetCalibrationStatus(ADCx));	 //等待校准结束
}

/**
 * @description: 读取 ADC 转换值
 * @param {uint8_t} adc_ch	ADC 通道
 * @return None
 * @Sample get_adc(0);
 */
uint16_t get_adc(uint8_t adc_ch)
{
  	//设置指定ADC的规则组通道，一个序列，采样时间
	ADC_RegularChannelConfig(using_adc, adc_ch, 1, ADC_SampleTime_239Cycles5);	//ADC通道,采样时间为239.5周期	  			    
	ADC_SoftwareStartConvCmd(using_adc, ENABLE);		//使能指定的ADC的软件转换
	 
	while(!ADC_GetFlagStatus(using_adc, ADC_FLAG_EOC ));//等待转换结束

	return ADC_GetConversionValue(using_adc);
}

/**
 * @description: 获取内部温度传感器温度值
 * @param  None
 * @return {short} CPU 温度(放大 100 倍后的 4 位整数)
 */
short get_temperate(void)
{
	uint16_t adcx;
 	float temperate;
	adcx = get_adc(ADC_Channel_16);
	
	/* 在25oC时的电压 1.43V，平均斜率 4.3mV/oC | (1.43 - 测得电压) / 0.0043 + 25 */
	temperate = (1775 - adcx) * 3.3 / 17.6128 + 25; 	// ( ) * 3.3 / 4096 / 0.0043 + 25
 
	return (short)(temperate * 100);
}
